import { Project } from 'ts-morph'
import { UseOptions } from '../../interface/cmd'
import { RequestMethods } from '../../interface/typescript'
import { generateJsTemplate, generateTsTemplate } from '../template'
import { handleModule, jsLine, jsPerfix, tsLine, tsPerfix } from './handler'
import fs from 'fs'
import path from 'path'
import { getRequestMethod } from '../../utils'

/**写入文件头 */
function usePerfix(tsDefineFilename: string, option: UseOptions) {
  return option.js ? jsPerfix(tsDefineFilename, option) : tsPerfix(tsDefineFilename, option)
}
/**写入文件内容 */
function useLine(
  apiName: string,
  reqName: string,
  rspName: string,
  requestMethod: RequestMethods,
  baseUrl: string,
  option: UseOptions
) {
  return option.js
    ? jsLine(apiName, reqName, rspName, requestMethod, baseUrl)
    : tsLine(apiName, reqName, rspName, requestMethod, baseUrl)
}

function writeFile(
  tsDefineDirname: string,
  tsDefineFilename: string,
  apiline: string,
  option: UseOptions
) {
  return option.js
    ? writeJsFile(tsDefineDirname, tsDefineFilename, apiline)
    : writeTsFile(tsDefineDirname, tsDefineFilename, apiline)
}

// 写入js文件
function writeJsFile(tsDefineDirname: string, tsDefineFilename: string, apiline: string) {
  const p1 = fs.promises.writeFile(
    path.resolve(tsDefineDirname, tsDefineFilename.replace('.d.ts', '.js')),
    apiline
  )
  const p2 = generateJsTemplate(tsDefineDirname)
  return Promise.all([p1, p2])
}

// 写入ts文件
function writeTsFile(tsDefineDirname: string, tsDefineFilename: string, apiline: string) {
  const p1 = fs.promises.writeFile(
    path.resolve(tsDefineDirname, tsDefineFilename.replace('.d.ts', '.ts')),
    apiline
  )
  const p2 = generateTsTemplate(tsDefineDirname)
  return Promise.all([p1, p2])
}

/**
 *
 * @param pbtsFilePath .d.ts的文件路径
 */
export default async function useGenerateFile(pbtsFilePath: string, option: UseOptions) {
  const { baseUrl } = option
  // 获取当前d.ts文件的目录名称和文件名称
  const tsDefineDirname = path.dirname(pbtsFilePath)
  const tsDefineFilename = path.basename(pbtsFilePath)
  let apiline: string = ''
  apiline += usePerfix(tsDefineFilename, option)
  // 处理ts
  const project = new Project()
  project.addSourceFileAtPath(pbtsFilePath)
  const file = project.getSourceFileOrThrow(pbtsFilePath) // 获取生成的文件
  const modules = file.getModules() // 获取所有的moddule类
  handleModule(modules, (module, parentName) => {
    const interfaces = module.getInterfaces()
    interfaces.length &&
      interfaces.forEach((i) => {
        const reqName = i.getName()
        // 找到请求的interface名称
        const reqNameMatchs = reqName.match(/^I(\S*)Request$/)
        if (reqNameMatchs && reqNameMatchs.length) {
          const apiName = reqNameMatchs[1]
          // console.log(apiName)
          // 找到返回值的interface
          const rspName = `I${apiName}Reply`
          const rsp = interfaces.find((item) => item.getName() === rspName)
          if (!rsp) {
            return
          }
          apiline += useLine(
            apiName,
            `${parentName}.${reqName}`,
            `${parentName}.${rspName}`,
            getRequestMethod(apiName),
            baseUrl,
            option
          )
        }
      })
  })
  // 使用Promise.all写入所有文件
  await writeFile(tsDefineDirname, tsDefineFilename, apiline, option)
}
